package com.tencent.albert.weixin.driver.utils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.tencent.albert.weixin.driver.bean.AccessToken;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.*;
import java.net.*;
import java.util.Map;

/**
 * Created by albertzhu on 15/2/12.
 */
public class HttpUtil {

    private static Logger logger = LoggerFactory.getLogger(HttpUtil.class);

    private static final int BUFFER_SIZE = 4096;

    /**
     * Downloads a file from a URL
     *
     * @param openId
     * @param fileName
     * @param fileURL  HTTP URL of the file to be downloaded
     * @param saveDir  path of the directory to save the file
     * @throws java.io.IOException
     */
    public static String downloadFile(String openId, String fileName, String fileURL, String saveDir)
            throws IOException {
        logger.debug("HttpDownloadUtility", "start down file at " + fileURL);
        String saveFilePath = null;
        URL url = new URL(fileURL);
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
        int responseCode = httpConn.getResponseCode();

        // always check HTTP response code first
        if (responseCode == HttpURLConnection.HTTP_OK) {
            String disposition = httpConn.getHeaderField("Content-Disposition");
            String contentType = httpConn.getContentType();
            int contentLength = httpConn.getContentLength();
            if (contentType.equals("image/jpeg")) {
                fileName = fileName + ".jpg";
            }
            System.out.println("Content-Type = " + contentType);
            System.out.println("Content-Disposition = " + disposition);
            System.out.println("Content-Length = " + contentLength);
            System.out.println("fileName = " + fileName);
            String HashCode = Util.stringMD5(openId + "CLA");
            File dic = new File(saveDir + File.separator + String.valueOf(HashCode).substring(0, 6));
            if (!dic.exists()) {
                dic.mkdirs();
            }
            InputStream inputStream = null;
            FileOutputStream outputStream = null;
            try {
                inputStream = httpConn.getInputStream();
                saveFilePath = dic.getAbsolutePath() + File.separator + fileName;
                // opens an output stream to save into file
                outputStream = new FileOutputStream(saveFilePath);
                int bytesRead = -1;
                byte[] buffer = new byte[BUFFER_SIZE];

                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }

                outputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
                saveFilePath = null;
            } finally {
                if (null != inputStream) {
                    inputStream.close();
                }
                if (null != outputStream) {
                    outputStream.close();
                }
            }

            logger.debug("HttpDownloadUtility", "download file succ " + openId + " saveFilePath:" + saveFilePath);
        } else {
            logger.debug("HttpDownloadUtility", "download file error " + responseCode);
        }
        httpConn.disconnect();
        logger.debug("HttpDownloadUtility", "return saveFilePath " + saveFilePath);
        return saveFilePath;
    }

    public static String readContentFromGet(String getUrl,String encode) throws IOException {
        // 拼凑get请求的URL字串，使用URLEncoder.encode对特殊和不可见字符进行编码
        URL getURL = new URL(getUrl);
        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("web-proxy.oa.com", 8080));
        // 根据拼凑的URL，打开连接，URL.openConnection函数会根据URL的类型，
        // 返回不同的URLConnection子类的对象，这里URL是一个http，因此实际返回的是HttpURLConnection
        HttpURLConnection httpURLConnection = (HttpURLConnection) getURL.openConnection(proxy);
        try {
            httpURLConnection.connect();
            InputStream inptStream = httpURLConnection.getInputStream();
            return dealResponseResult(inptStream,encode);

        } finally {
            httpURLConnection.disconnect();
        }
    }

    public static String readContentFromPost(String postUrl, Map<String, String> params, String encode) throws IOException {
        byte[] data = getRequestData(params, encode).toString().getBytes();
        try {
            HttpURLConnection httpURLConnection = (HttpURLConnection) new URL(postUrl).openConnection();
            httpURLConnection.setConnectTimeout(3000);
            httpURLConnection.setDoInput(true);
            httpURLConnection.setDoOutput(true);
            httpURLConnection.setRequestMethod("POST");
            httpURLConnection.setUseCaches(false);
            //设置请求体的类型是文本类型
            httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            //设置请求体的长度
            httpURLConnection.setRequestProperty("Content-Length", String.valueOf(data.length));
            //获得输出流，向服务器写入数据
            OutputStream outputStream = httpURLConnection.getOutputStream();
            outputStream.write(data);

            int response = httpURLConnection.getResponseCode();
            if (response == HttpURLConnection.HTTP_OK) {
                InputStream inptStream = httpURLConnection.getInputStream();
                return dealResponseResult(inptStream,encode);
            }
        } finally {

        }
        return "";
    }

    public static StringBuffer getRequestData(Map<String, String> params, String encode) {
        StringBuffer stringBuffer = new StringBuffer();
        try {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                stringBuffer.append(entry.getKey())
                        .append("=")
                        .append(URLEncoder.encode(entry.getValue(), encode))
                        .append("&");
            }
            stringBuffer.deleteCharAt(stringBuffer.length() - 1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return stringBuffer;
    }

    public static String dealResponseResult(InputStream inputStream,String encodeing) throws UnsupportedEncodingException {
        String resultData = null;      //存储处理结果
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byte[] data = new byte[1024];
        int len = 0;
        try {
            while ((len = inputStream.read(data)) != -1) {
                byteArrayOutputStream.write(data, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        resultData = new String(byteArrayOutputStream.toByteArray(),encodeing);
        return resultData;
    }

    public static String readRespByGet(String requestUrl, String requestMethod,
                                       String outputStr) {
        StringBuilder buffer = new StringBuilder();
        try {
            // 创建SSLContext对象，并使用我们指定的信任管理器初始化
            TrustManager[] tm = {new MyX509TrustManager()};
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url
                    .openConnection();
            httpUrlConn.setSSLSocketFactory(ssf);

            httpUrlConn.setDoOutput(true);
            httpUrlConn.setDoInput(true);
            httpUrlConn.setUseCaches(false);
            // 设置请求方式（GET/POST）
            httpUrlConn.setRequestMethod(requestMethod);

            if ("GET".equalsIgnoreCase(requestMethod)) {
                httpUrlConn.connect();
            }

            // 当有数据需要提交时
            if (null != outputStr) {
                OutputStream outputStream = httpUrlConn.getOutputStream();
                // 注意编码格式，防止中文乱码
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 将返回的输入流转换成字符串
            InputStream inputStream = httpUrlConn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(
                    inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(
                    inputStreamReader);

            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            // 释放资源
            inputStream.close();
            inputStream = null;
            httpUrlConn.disconnect();
            Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create();
            String temp = buffer.toString();
            //System.out.println("read temp:"+temp);
            return temp;
        } catch (ConnectException ce) {
            logger.debug("Weixin server connection timed out.");
        } catch (Exception e) {
            logger.debug("https request error:{}", e);
        }
        return null;
    }

    public static AccessToken getAccessTokenByGet(String requestUrl, String requestMethod,
                                                  String outputStr) {
        String temp = readRespByGet(requestUrl,requestMethod,outputStr);
        Gson gson = new Gson();
        AccessToken token = gson.fromJson(temp,AccessToken.class);
        return token;
    }

    /**
     * 发起https请求并获取结果
     *
     * @param requestUrl    请求地址
     * @param requestMethod 请求方式（GET、POST）
     * @param outputStr     提交的数据
     * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
     */
    public static Map<String, String> httpRequest(String requestUrl, String requestMethod,
                                                  String outputStr) {
        StringBuilder buffer = new StringBuilder();
        try {
            // 创建SSLContext对象，并使用我们指定的信任管理器初始化
            TrustManager[] tm = {new MyX509TrustManager()};
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url
                    .openConnection();
            httpUrlConn.setSSLSocketFactory(ssf);

            httpUrlConn.setDoOutput(true);
            httpUrlConn.setDoInput(true);
            httpUrlConn.setUseCaches(false);
            // 设置请求方式（GET/POST）
            httpUrlConn.setRequestMethod(requestMethod);

            if ("GET".equalsIgnoreCase(requestMethod)) {
                httpUrlConn.connect();
            }

            // 当有数据需要提交时
            if (null != outputStr) {
                OutputStream outputStream = httpUrlConn.getOutputStream();
                // 注意编码格式，防止中文乱码
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 将返回的输入流转换成字符串
            InputStream inputStream = httpUrlConn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(
                    inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(
                    inputStreamReader);

            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            // 释放资源
            inputStream.close();
            inputStream = null;
            httpUrlConn.disconnect();
            Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create();
            String temp = buffer.toString();
            //System.out.println("read temp:"+temp);
            Map<String, String> retMap = gson.fromJson(temp, new TypeToken<Map<String, String>>() {
            }.getType());
            return retMap;
        } catch (ConnectException ce) {
            logger.debug("Weixin server connection timed out.");
        } catch (Exception e) {
            logger.debug("https request error:{}", e);
        }
        return null;
    }


}
